package com.atguigu.gmall.service.impl;

import com.alibaba.nacos.client.utils.StringUtils;
import com.atguigu.gmall.entity.BaseBrand;
import com.atguigu.gmall.mapper.BaseBrandMapper;
import com.atguigu.gmall.service.BrandService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.bind.Element;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Transactional
@Service
public class BrandServiceImpl extends ServiceImpl<BaseBrandMapper, BaseBrand> implements BrandService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public IPage<BaseBrand> selectBrandByPage(Page<BaseBrand> baseBrandPage) {
        //设置条件
        QueryWrapper<BaseBrand> queryWrapper = new QueryWrapper<>();
        return baseMapper.selectPage(baseBrandPage, queryWrapper);
    }

    @Override
    public List<BaseBrand> getAllBrand() {
        return baseMapper.selectList(null);
    }

    public  void setNum01() {

        String uuid = String.valueOf(UUID.randomUUID());
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 3, TimeUnit.SECONDS);
        if (lock) {
            //获取到了锁
            String value = (String) redisTemplate.opsForValue().get("num");
            if (StringUtils.isBlank(value)) {
                this.redisTemplate.opsForValue().set("num", "1");
                this.redisTemplate.delete("lock");//删除锁
                return;
            }
            int num = Integer.parseInt(value);
            // 把redis中的num值+1
            this.redisTemplate.opsForValue().set("num", String.valueOf(++num));
            //  定义一个lua 脚本
            String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            redisScript.setScriptText(script);
            redisScript.setResultType(Long.class);
            //删除key
            redisTemplate.execute(redisScript, Arrays.asList("lock"), uuid);
        } else {
            //没拿到锁
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setNum();//自旋
        }
    }
    @Override
    public  void setNum(){
        RLock lock = redissonClient.getLock("lock");
        try {
            boolean b = lock.tryLock(100, 10, TimeUnit.SECONDS);
            if (b){
                String value = (String) redisTemplate.opsForValue().get("num");
                if (StringUtils.isEmpty(value)){
                    redisTemplate.opsForValue().set("num", "1");
                }else {
                    int num = Integer.parseInt(value);
                    redisTemplate.opsForValue().set("num", String.valueOf(++num));
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}
